#include "buddychat.h"

#include "qun.hpp"
#include "qqclient.hpp"
#include <QDateTime>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QScrollBar>
#include "qtq_config.h"
#include "util.hpp"
#include <QDebug>

#include "db.h"
#include "debug.hpp"
#include "map"

extern qqclient* qq;
using namespace std;
extern char*buddy_buf;
extern GroupByUIdInfoRecords gGoupedInforecords;//分组信息暂存
extern QString myqq_get_buddy_name( qqclient* qq, uint uid );

extern int myqq_send_im_to_buddy( qqclient* qq, uint int_uid, char* msg, int wait );
extern int myqq_send_im_to_qun( qqclient* qq, uint int_uid, char* msg, int wait );
extern char* util_escape( char* str );
BuddyChat* buddychatWin = NULL;
BuddyChat::BuddyChat(QWidget *parent) :
    QDialog(parent),currentTabIndex(-1)
{
    Ui::BuddyChat::setupUi(this);
    txtMessageHistory->setReadOnly(true);
    lstFastReplay->setVisible( false );
    lvwEmote->setVisible( false );
    lvwEmote->setDragEnabled(false);
    connect(lvwEmote, SIGNAL( clicked(const QModelIndex &) ), this, SLOT(OnEmoteClick(const QModelIndex &)));
    gboxBuddyInfo->setVisible( false );

    tabBuddys->clear();

    connect(lblClose,SIGNAL(Clicked(QClickedLabel*)),this,SLOT(OnCloseClicked()));
    connect(tabBuddys,SIGNAL(tabCloseRequested(int)), this, SLOT(buddyTabCloseRequested(int)));
    connect(tabBuddys,SIGNAL(currentChanged(int)), this, SLOT(currentChanged(int)));

    connect(this, SIGNAL(NewMsgReached()), this,  SLOT(OnProcessMsg()));

    connect( lblReturn, SIGNAL(Clicked(QClickedLabel*)),this, SLOT(close()) );
    connect( lblSend,SIGNAL(Clicked(QClickedLabel*)),this, SLOT(btn_sendClick(QClickedLabel*)));
    connect( lstFastReplay, SIGNAL(itemClicked(QListWidgetItem *)),this,SLOT(OnFastReplay(QListWidgetItem *)));
    connect( lblPreinfo,SIGNAL(Clicked(QClickedLabel*)),this, SLOT(toogleDisplayFastReplayPanel()));
    connect( lblEmote,SIGNAL(Clicked(QClickedLabel*)),this, SLOT(toogleDisplayEmotePanel()));
    connect( lblInfo,SIGNAL(Clicked(QClickedLabel*)),this, SLOT(toogleBuddyInfoPanel()));

    tabBuddys->setStyleSheet("\
                QTabWidget::pane{background-color: rgba(255,0,255,50);border-width:0px; min-height:40px;}\
                QTabWidget::tab-bar{background-color:rgba(255,0,255,64);border-width:0px; min-height: 40px;}\
                //QTabBar::tab {background-image: url(:/OK/skins/tab button.png);\
                border-bottom-color: #FF00FF;\
                border-top-left-radius: 0px;\
                border-top-right-radius: 0px;\
               //min-width: 140px;min-height: 116px;\
                padding: 10px;\
            }\
            QTabBar::tab{\
                min-height: 40px;\
            }\
            QTabBar::tab:!selected {\
                background-color: rgba(255, 125, 255,30);margin-top: 0px;\
            }\
            QTabBar::tab:selected {\
                background-color: rgba(255,0,255,70);\
                //background-image: url(:/OK/skins/musicselect.png);\
            }\
            QTabBar::tab:first:selected {\
                margin-left: 0;\
            }\
            QTabBar::tab:last:selected {\
                margin-right: 0;\
            }\
            QTabBar::tab:only-one {\
                margin: 0;\
            }");

    changeBG(0);
}

void BuddyChat::initEmoteList()
{
    QStandardItemModel *model = (QStandardItemModel*)lvwEmote->model();
    if(model != NULL)
        return;
    model =  new QStandardItemModel();

    lvwEmote->setViewMode( QListView::IconMode );
    lvwEmote->setIconSize(QSize(40,40));

    lvwEmote->setModel(model);

    for(uint i=0;i<emoticons_std_num;i ++)
    {
        uint symbol = emoticons_std[i].symbol;
        QStandardItem *item = new QStandardItem();
        QString iconFile = QString(RC_PREFIX "/face/QQTheme/face/facen%1.PNG").arg(symbol);
        item->setIcon(QIcon( QPixmap(iconFile) ));
        item->setEditable(false);
        model->appendRow(item);
    }
}
void BuddyChat::OnEmoteClick(const QModelIndex &index)
{
    unsigned char symbol = emoticons_std[index.row()].symbol;
    DBG("input row:%d,emote: 0x%2x",index.row(),symbol);
    txtMessageSend->insertHtml(QString("<img src=':/face/QQTheme/face/facen%1.PNG' />").arg( symbol ));
    lvwEmote->setVisible(false);
}

void BuddyChat::toogleDisplayFastReplayPanel()
{
    bool bVisible = lstFastReplay->isVisible() ;
    lstFastReplay->setVisible( !bVisible );
    lstFastReplay->raise();
}
void BuddyChat::toogleDisplayEmotePanel()
{
    initEmoteList();
    bool bVisible = lvwEmote->isVisible() ;
    lvwEmote->setVisible( !bVisible );
    lvwEmote->raise();
}
void BuddyChat::toogleBuddyInfoPanel()
{
    bool bVisible = gboxBuddyInfo->isVisible() ;
    gboxBuddyInfo->setVisible( !bVisible );
    gboxBuddyInfo->raise();
}
void BuddyChat::EmitMSG()
{
    emit NewMsgReached();
};
void BuddyChat::OnProcessMsg()
{
    db &infoDB = db::GetInstance();
    infoDB.mutex_chat.lock();
    QWidget* widget = tabBuddys->currentWidget();
    uint type = getTYPEByWidget( widget );
    //uint ownerID = qq->number;
    uint friendID = getUIDbyWidget( widget );
    InfoRecords* infos = gGoupedInforecords[friendID];

    if(infos)
    {
        std::vector<STR_inforecord>::iterator it;
        for(it = infos->begin();it != infos->end(); it++)
        {

            STR_inforecord record = *it;
            QDateTime time = QDateTime::fromTime_t(record.time);
            char nickName[40] = "";
            GetMemberNickName(type,record.fromid,record.toqunid,nickName);
            QString splitter = QString("<p style=\" margin-top:25px; margin-bottom:25px; margin-left:5px; margin-right:5px; -qt-block-indent:0; text-indent:0px;\">%1</p>");

            txtMessageHistory->append(QString("%1(%2)  %3").arg( QString::fromUtf8(nickName) ).arg(record.fromid).arg(time.toString("yyyy-MM-dd hh:mm:ss")));

            QString info = record.info;
            QRegExp exp("\\[face\\:(\\d*)\\]");
            info.replace(exp,"<img src=':/face/QQTheme/face/facen\\1.PNG' />");
            txtMessageHistory->append( info );
            txtMessageHistory->append(splitter.arg("<img height='50px' width='300px' src=':/QQTheme/Splitter.png' /><br>"));

            txtMessageHistory->verticalScrollBar()->setValue(txtMessageHistory->verticalScrollBar()->maximumHeight());
        }
        //delete infos;
        gGoupedInforecords.erase(friendID);
    }
    infoDB.mutex_chat.unlock();
}
void BuddyChat::Talk(QString &planInfo,QString &htmlInfo)
{
    QString tempStr = htmlInfo;
    tempStr.replace(QRegExp("<img src=\":/face/QQTheme/face/facen(\\d*)\\.PNG\" />"),"[face:\\1]");
    QDateTime now = QDateTime::currentDateTime ();
    QWidget* widget = tabBuddys->currentWidget();

    uint fromuid = qq->number;
    uint touid = getUIDbyWidget( widget );

    uint type = getTYPEByWidget(tabBuddys->currentWidget());

    QTextDocument document;

    document.setHtml(tempStr);

    QString sInfo = document.toPlainText();
    //sInfo.replace(QRegExp("[face:(\\d*)]"),"\x14\\1]");
    if( type ==0 )
    {
        myqq_send_im_to_buddy( qq, touid, sInfo.toUtf8().data(), 0 );
    }
    else if(type == 1)
    {
        myqq_send_im_to_qun( qq, touid, sInfo.toUtf8().data(), 0 );
    }
    if(false)
    {}
    else
    {
        uint _toqunid = type == 0 ? 0 : touid;
        STR_inforecord record;
        record.type = type;
        record.fromid = fromuid;
        record.toid = type == 0 ? touid : 0;
        record.toqunid = _toqunid;
        record.time = now.toTime_t();
        record.info = sInfo;

        db &infoDB = db::GetInstance();
        infoDB.pushRecord(0, touid, record);

        /*db &infoDB = db::GetInstance();
        infoDB.open(qq->number);
        uint _touid = type == 0 ? touid : 0;
        uint _toqunid = type == 0 ? 0 : touid;
        infoDB.writeRecord(type,fromuid, _touid, _toqunid, now.toTime_t(), sInfo);
        */

        char nickName[40] = "";
        GetMemberNickName(type,fromuid,_toqunid,nickName);
        QString splitter = QString("<p style=\" margin-top:25px; margin-bottom:25px; margin-left:5px; margin-right:5px; -qt-block-indent:0; text-indent:0px;\">%1</p>");
        txtMessageHistory->append(QString("%1(%2)  %3").arg( QString::fromUtf8(nickName) ).arg(qq->number).arg(now.toString("yyyy-MM-dd hh:mm:ss")));
        txtMessageHistory->append(htmlInfo);
        txtMessageHistory->append(splitter.arg("<img height='50px' width='300px' src=':/QQTheme/Splitter.png' /><br>"));
        txtMessageSend->clear();
    }
}
void BuddyChat::OnFastReplay(QListWidgetItem *item)
{
    QString sinfo = item->text();
    QString hinfo = item->text();
    Talk(sinfo,hinfo);
    lstFastReplay->setVisible( false );
}
void BuddyChat::btn_sendClick(QClickedLabel*)
{
    QString sinfo = txtMessageSend->toPlainText();
    QString hinfo = txtMessageSend->toHtml();
    if(sinfo.length()<=0)
    {
        lstFastReplay->setVisible( !lstFastReplay->isVisible() );
    }
    else
    {
        Talk(sinfo,hinfo);
    }
}
void BuddyChat::currentChanged(int index)
{
    if(index < 0)
        return;

    //uint ownerId = qq->number;
    ChatObj *co = this->getChatObjByWidget(tabBuddys->currentWidget());
    if(co == NULL)
        return;
    uint uid = co->number;
    uint type= co->type;
    //changeBG(type);
    if(currentTabIndex != index)
    {
        loadRecordFromDB(uid,type);
        currentTabIndex = index;
    }
}
void BuddyChat::OnCloseClicked()
{
    if(this->currentTabIndex>=0)
    {
        //tabBuddys->removeTab(this->currentTabIndex);
        buddyTabCloseRequested(this->currentTabIndex);
    }
}
void BuddyChat::buddyTabCloseRequested(int index)
{
    this->currentTabIndex = -1;
    if(tabBuddys->count()>0)
    {
        char key[20] = "";
        QWidget* widget = tabBuddys->widget(index);
        uint type = getTYPEByWidget( widget );
        uint id = getUIDbyWidget( widget );
        qsnprintf(key,sizeof(key)-1,"%d-%d",type,id);
        m_QQbuddy.erase(key);
        tabBuddys->removeTab(index);
    }
    if(tabBuddys->count()<=0)
    {
        this->close();
        //buddychatWin = NULL;
    }

}
bool BuddyChat::UidIsTalking(uint uid,uint type)
{
    char key[20] = "";
    qsnprintf(key,sizeof(key)-1,"%d-%d",type,uid);
    map<string,ChatObj*>::iterator it = m_QQbuddy.find(key);
    if( it != m_QQbuddy.end())
    {
        ChatObj* obj = m_QQbuddy[key];
        QWidget *widget = obj->widget;
        return widget == tabBuddys->currentWidget();
    }
    else
    {
        return false;
    }
}
static int myqq_get_qun_member_list( qqclient* qq, uint int_uid, char* buf, int size, char online )
{
        qqqun * q = qun_get( qq, int_uid, 0 );
        if( !q )return 0;
        //Hope the Qun won't get removed while we are using it.
        int len = 0, ln = 1;
        buf[0] = 0;
		q->member_list_lock.lock();
		for(qqqun::member_list_type::iterator i=q->member_list.begin();
			i!=q->member_list.end();++i){        
                qunmember* m = *i;
                if( online && m->status == QQ_OFFLINE ) continue;
                len = qsnprintf( buf,size-1, "%s%-8d%-16d%-16s%-16.64s\n", buf, ln++, m->number,
                        (m->role&1)?"Admin":"Fellow", util_escape( m->nickname ) );
                if( len + 80 > size )
                        break;
        }
		q->member_list_lock.unlock();        
        return len;
}

void BuddyChat::changeBG(uint type)
{
    static uint lasttype = 255;
    if(type != lasttype)
    {
        if(type == 0)
        {
            lblBG->setPixmap(QPixmap(RC_PREFIX "QQTheme/MSG.PNG"));
            txtMessageSend->setGeometry(QRect(10,670,450,50));
            txtMessageHistory->setGeometry(QRect(0,100,480,560));
        }
        else
        {
            lblBG->setPixmap(QPixmap(RC_PREFIX "QQTheme/MSG2.PNG"));
            txtMessageSend->setGeometry(QRect(120,670,340,50));
            txtMessageHistory->setGeometry(QRect(70,86,410,573));
        }
        lasttype = type;
    }
}
void BuddyChat::ActiveTabByUid(uint number,QString nickName,uint type)
{
    //changeBG(type);
    m_type = type;
    QApplication::setActiveWindow(this);
    char key[20] = "";
    qsnprintf(key,sizeof(key)-1,"%d-%d",type,number);
    int itemIndex = 0;
    QWidget *widget;

    if(m_QQbuddy.find(key) == m_QQbuddy.end())
    {
        widget = new QLabel("");
        widget->resize(0,0);
        ChatObj *co = new ChatObj;
        co->type = type;
        co->number = number;
        co->widget = widget;
        m_QQbuddy[key] = co;
        itemIndex = tabBuddys->addTab(widget,QString("%1").arg(nickName));
    }
    else
    {
        ChatObj *co = m_QQbuddy[key];
        widget = co->widget;
        itemIndex = tabBuddys->indexOf(widget);
    }
    if(currentTabIndex != itemIndex)
    {
        currentTabIndex = itemIndex;
        tabBuddys->setCurrentIndex(itemIndex);
        loadRecordFromDB(number,type);
    }
    gGoupedInforecords.erase(number);

}
map<uint,bool> qunInitStatus;
void BuddyChat::GetMemberNickName(uint type,uint number,uint qun_number,char* nickName)
{

    if(type == 0)
    {
        qqbuddy* buddy = buddy_get(  qq, number, 0 );
        if(buddy)
            strcpy(nickName , buddy->nickname);
    }
    else // qun member
    {
        db &infoDB = db::GetInstance();
        infoDB.open(qq->number);
        bool iSucess = infoDB.getQunMemberName(qun_number, number, &nickName[0]);
        if(!iSucess)
        {
            bool isInitList = qunInitStatus[qun_number];
            qqqun * q = qun_get( qq, qun_number , 0 );
            if(q && !isInitList)
            {
                infoDB.pushQun(q);
                qunInitStatus[qun_number] = true;
            }
        }
    }
}
void BuddyChat::loadRecordFromDB(uint uid,uint type)
{
    db &infoDB = db::GetInstance();
    infoDB.open(qq->number);
    static InfoRecords vRecord;
    uint ownerId = qq->number;

    uint ret = infoDB.readRecord(vRecord, ownerId, uid,type);
    DBG( "recordsize: %d", ret );

    txtMessageHistory->clear();
    for(int i=vRecord.size() - 1;i>= 0;i--)
    {
        STR_inforecord record = vRecord[i];
        QDateTime time = QDateTime::fromTime_t(record.time);


        char nickName[40] = "";
        GetMemberNickName(type,record.fromid,record.toqunid,nickName);

        QString splitter = QString("<p style=\" margin-top:25px; margin-bottom:25px; margin-left:5px; margin-right:5px; -qt-block-indent:0; text-indent:0px;\">%1</p>");

        txtMessageHistory->append(QString("%1(%2)  %3").arg( QString::fromUtf8(nickName) ).arg(record.fromid).arg(time.toString("yyyy-MM-dd hh:mm:ss")));


        //QString info = record.info;
        QString info = QString("<p style=\" margin-top:5px; margin-bottom:5px; margin-left:5px; margin-right:5px; -qt-block-indent:0; text-indent:0px;\">%1</p>").arg(record.info);
        QRegExp exp("\\[face\\:(\\d*)\\]");
        info.replace(exp,"<img src=':/face/QQTheme/face/facen\\1.PNG' />");
        txtMessageHistory->append(info);


        txtMessageHistory->append(splitter.arg("<img height='50px' width='300px' src=':/QQTheme/Splitter.png' /><br>"));

    }
}
uint BuddyChat::getTYPEByWidget(QWidget* widget)
{
    ChatObj *obj = getChatObjByWidget(widget);
    if(obj != NULL)
        return obj->type;
    else
        return 0;
}
ChatObj *BuddyChat::getChatObjByWidget(QWidget* widget)
{
    map<string,ChatObj*>::iterator it;
    for(it = m_QQbuddy.begin(); it != m_QQbuddy.end(); it++)
    {
        ChatObj* obj = it->second;

        QWidget* w = obj->widget;
        if(w == widget )
        {
            return obj;
        }
    }
    return NULL;
}
uint BuddyChat::getUIDbyWidget(QWidget* widget)
{
    ChatObj *obj = getChatObjByWidget(widget);
    if(obj)
        return obj->number;
    else
        return 0;
}

void BuddyChat::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        retranslateUi(this);
        break;
    default:
        break;
    }
}
